#pragma once

#include <stddef.h>
#include <stdint.h>
#include "ringbuffer_err.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef uint32_t buf_size_t;

typedef struct RingBufferNode_t RingBufferSection;
struct RingBufferNode_t {
    uint8_t *buf;
    buf_size_t buflen;
    RingBufferSection *next;
};

typedef struct BufferPos_t BufferPos;
struct BufferPos_t {
    RingBufferSection *sect;
    buf_size_t offset;
};

typedef struct RingBuffer_type RingBuffer;
struct RingBuffer_type
{
    BufferPos head;
    BufferPos tail;
    // RingBufferSection static_buffer;
    RingBufferSection *buffer_list;
    buf_size_t total_buf_len;
    buf_size_t used_buf_len;   // used len not equal valid len
    buf_size_t (*get_total_count)(RingBuffer *const self);
    buf_size_t (*get_free_count)(RingBuffer *const self);
    buffer_err (*extent_static_buffer)(RingBuffer *const self, RingBufferSection *buffer_sect);
    buffer_err (*extend_dynamic_buffer)(RingBuffer *const self, buf_size_t size);
    buffer_err (*write)(RingBuffer *const self, uint8_t *buf, buf_size_t buflen);
    buffer_err (*read)(RingBuffer *const self, uint8_t *buf, buf_size_t buflen);
};

buffer_err RingBuffer_Ctor(RingBuffer *const buffer);

#ifdef __cplusplus
}
#endif
